package com.swt.testdemo.service.impl;


import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.swt.testdemo.config.ResponseBean;
import com.swt.testdemo.config.ResponseMessage;
import com.swt.testdemo.dao.StudentDao;
import com.swt.testdemo.dao.SysCaptchaDao;
import com.swt.testdemo.dao.SysUserDao;
import com.swt.testdemo.entity.StudentEntity;
import com.swt.testdemo.entity.SysCaptchaEntity;
import com.swt.testdemo.exception.AgyException;
import com.swt.testdemo.form.CreateStudentForm;
import com.swt.testdemo.form.EditStudentForm;
import com.swt.testdemo.form.QueryStudentForm;
import com.swt.testdemo.form.SysLoginForm;
import com.swt.testdemo.service.StudentService;
import com.swt.testdemo.shiro.ShiroUtils;
import com.swt.testdemo.shiro.UsernamePasswordMacToken;
import com.swt.testdemo.util.RedisUtil;
import com.swt.testdemo.util.ValidatorUtil;
import com.swt.testdemo.vo.StudentInfoVo;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author BleethNie
 * @version 1.0
 * @date 2020-01-08 17:48
 **/
@Service("StudentService")
public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> implements StudentService {



    private static DateTime LAST_DELETE_CAPTION_TIME;

    // @Value(value = "${swt.login.mac}")
    private boolean swtLoginMac;

    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    private SysCaptchaDao sysCaptchaDao;


    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private StudentDao studentDao;



    @Override
    public ResponseBean listStudent() {
        List<StudentEntity> studentEntities = studentDao.listStudent();
        return new ResponseBean(200,"查询成功",studentEntities);
    }

    @Override
    public ResponseBean listStuInfo(QueryStudentForm form) {


        //参数校验
        ValidatorUtil.validateEntity(form);

        String stuNameFilter = form.getStuNameFilter();
        String stuAgeFilter = form.getStuAgeFilter();

        Page<StudentEntity> entityPage = new Page<>(form.getPage(), form.getLimit());
        IPage<StudentEntity> resultPage = studentDao.listStu(entityPage, stuNameFilter, stuAgeFilter);
        return new ResponseBean(200, "查询成功", resultPage);

    }

    @Override
    public ResponseMessage addStu(CreateStudentForm form) {

        //参数校验
        ValidatorUtil.validateEntity(form);


        StudentEntity studentEntity = new StudentEntity();
        BeanUtils.copyProperties(form,studentEntity);

        DateTime current = DateUtil.date();
        studentEntity.setCreatedTime(current);
        studentEntity.setUpdateTime(current);

        studentEntity.setStatus(StudentEntity.STATUS_OK);
        this.save(studentEntity);
        return new ResponseMessage(200,"保存成功");
    }

    @Override
    public ResponseMessage editStuInfo(EditStudentForm form) {

        String key ="stu:info"+form.getId();
        redisUtil.del(key);

        //参数校验
        ValidatorUtil.validateEntity(form);

        StudentEntity studentEntity = new StudentEntity();
        BeanUtils.copyProperties(form,studentEntity);
        DateTime current = DateUtil.date();
        studentEntity.setUpdateTime(current);

        this.updateById(studentEntity);

        return new ResponseMessage(200,"修改成功");
    }



    @Override
    public ResponseBean showStuInfo(Integer stuId) {
        String key = "stu:info"+stuId;
        StudentInfoVo studentInfoVo = redisUtil.getObject(key, StudentInfoVo.class);
        if (studentInfoVo == null){
            StudentEntity studentEntity = this.getById(stuId);
            if (studentEntity == null){
                throw new AgyException("查询的学生不存在，请检查后重试....");
            }
            StudentEntity entity = studentDao.getByStuId(stuId);
            studentInfoVo = new StudentInfoVo();
            BeanUtils.copyProperties(entity,studentInfoVo);

        }
        redisUtil.setObject(key,studentInfoVo, RedisUtil.ONE_HOUR_EXPIRE_TIME);



        return new ResponseBean(200,"查询单个学生实体信息成功",studentInfoVo);
  }

    @Override
    public ResponseMessage deleteStuInfo(Integer stuId) {
        String key = "stu:info"+stuId;
        redisUtil.del(key);

        StudentEntity entity = this.getById(stuId);
        if (entity == null){
            throw new AgyException("该学生信息不存在，请检查后重试.....");
        }

        entity = new StudentEntity();
        entity.setId(stuId);
        entity.setStatus(StudentEntity.STATUS_DELETE);

        this.updateById(entity);
        return new ResponseMessage(200,"删除成功");
    }

    @Override
    public ResponseMessage login(SysLoginForm form) {
        HttpStatus httpStatus = HttpStatus.OK;

        //参数校验
        ValidatorUtil.validateEntity(form);


        //验证码校验
        String uuid = form.getUuid();
        String captcha = form.getCaptcha();
        String username = form.getUsername();
        String mac = form.getMac();


        SysCaptchaEntity sysCaptchaEntity = sysCaptchaDao.queryEntityByUuid(uuid);

        if (sysCaptchaEntity == null){
            httpStatus= HttpStatus.INTERNAL_SERVER_ERROR;
            return new ResponseMessage(httpStatus.value(),"验证发校验失败");
        }

        String sysCaptCha = sysCaptchaEntity.getCaptcha();
        sysCaptchaDao.useEntity(uuid);
        if (StrUtil.isEmpty(sysCaptCha) || !StrUtil.equalsIgnoreCase(sysCaptCha,captcha)){
            httpStatus= HttpStatus.INTERNAL_SERVER_ERROR;;
            return new ResponseMessage(httpStatus.value(),"验证码校验失败");
        }
        String message = "登陆成功";
        Subject subject = ShiroUtils.getSubject();
        try {
            UsernamePasswordToken token = null;
            if (swtLoginMac) {
                token = new UsernamePasswordMacToken(username, form.getPassword(), mac);
            } else {
                token = new UsernamePasswordToken(username, form.getPassword());
            }
            subject.login(token);
            sysUserDao.updateUserLoginFail("1", username, 0);
        } catch (UnknownAccountException e) {
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            message = e.getMessage();
        } catch (IncorrectCredentialsException e) {
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            Integer failCount = sysUserDao.selectUserLoginFail(username);
            if (failCount == null) {
            } else if (failCount >= 2) {
                message = "账号已被锁定,请联系管理员";
                sysUserDao.updateUserLoginFail("0", username, 0);
            } else {
                failCount++;
                message = "密码错误,剩余重试次数" + (3 - failCount) + "次";
                sysUserDao.updateUserLoginFail("1", username, failCount);
            }
        } catch (LockedAccountException e) {
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            message = e.getMessage();
        } catch (AccountException e) {
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            message = e.getMessage();
        } catch (AuthenticationException e) {
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            message = e.getMessage();
        }
        return new ResponseMessage(httpStatus.value(), message);

    }

    @Override
    public ResponseMessage logout() {
        ShiroUtils.logout();
        return new ResponseMessage(HttpStatus.OK.value(),"注销成功");
    }

    @Override
    public byte[] captcha(String uuid) {
       //每天删除一次captcha 表记录
        DateTime current = DateUtil.date();
        DateTime before30Day = current.offset(DateField.DAY_OF_MONTH, -30);
        DateTime before1Day = current.offset(DateField.DAY_OF_MONTH, -1);
        DateTime expireDay = current.offset(DateField.MINUTE, 5);
        if (LAST_DELETE_CAPTION_TIME == null){
           LAST_DELETE_CAPTION_TIME = current;
           sysCaptchaDao.deleteHistoryCaptcha(before30Day.toString());
        }
        if (LAST_DELETE_CAPTION_TIME.isBefore(before1Day)){
            LAST_DELETE_CAPTION_TIME = current;
            sysCaptchaDao.deleteHistoryCaptcha(before30Day.toString());
        }
        //生成captcha
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(150, 50);
        String code = captcha.getCode();
        SysCaptchaEntity sysCaptchaEntity = new SysCaptchaEntity();
        sysCaptchaEntity.setStatus(SysCaptchaEntity.STATUS_VALID);
        sysCaptchaEntity.setUuid(uuid);
        sysCaptchaEntity.setCaptcha(code);
        sysCaptchaEntity.setCreatedTime(current);
        sysCaptchaEntity.setExpireTime(expireDay);
        sysCaptchaDao.insert(sysCaptchaEntity);
        return captcha.getImageBytes();

    }

    @Override
    public ResponseMessage crackUUid(String uuid) {
       SysCaptchaEntity sysCaptchaEntity = new SysCaptchaEntity();
       sysCaptchaEntity.setUuid(uuid);
       sysCaptchaEntity.setStatus(SysCaptchaEntity.STATUS_VALID);
        QueryWrapper<SysCaptchaEntity> wq = new QueryWrapper<>();
        wq.eq("uuid",uuid);
        sysCaptchaDao.update(sysCaptchaEntity,wq);

        return new ResponseMessage(HttpStatus.OK.value(),"破解成功");
    }


}
